/* The code examples copyrighted by Nokia Corporation that are included to
 * this material are licensed to you under following MIT-style License:
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#include "calendarmodel.h"

CalendarModel::CalendarModel(QObject *parent, mKCal::ExtendedCalendar::Ptr calendar, mKCal::ExtendedStorage::Ptr myStorage, const QDate &date)
    : QAbstractListModel(parent)
{
    myCalendar = calendar;
    storage = myStorage;
    storage->open();

    QHash<int, QByteArray> roles;
    roles[EventStartTimeRole] = "eventstarttime";
    roles[EventEndTimeRole] = "eventendtime";
    roles[EventSummaryRole] = "eventsummary";
    roles[EventDescriptionRole] = "eventdescription";
    roles[EventLocationRole] = "eventlocation";
    roles[EventRecurringRole] = "eventrecurring";
    roles[EventUidRole] = "eventuid";
    setRoleNames(roles);
    dateChanged(date);
}

CalendarModel::~CalendarModel()
{
    // Save calendar changes before exit
    storage->save();
    storage->close();
}

void CalendarModel::dateChanged(const QDate &date)
{
    viewDate = date;

    beginResetModel();

    // Clear current list
    if(eventUid.size() > 0) {
        eventUid.clear();
    }

    storage->loadRecurringIncidences();
    storage->load(date);
    KCalCore::Event::Ptr event;
    KCalCore::Event::List newEvents = myCalendar->events(KDateTime(date));

    if(newEvents.size() > 0) {
        foreach(event, newEvents) {
            eventUid.append(event->uid());
        }
    }
    endResetModel();
}

// Returns true if event occurs on specified date, otherwise false.
bool CalendarModel::eventOccursOnDate(const KCalCore::Event::Ptr &event, const QDate &date)
{
    bool occursOnDate;
    if(event->dtStart().daysTo(KDateTime(date)) >= 0 &&
            date.daysTo(event->dtEnd().date()) >= 0) {
        occursOnDate = true;
    }
    else if(event->recurs() &&
            event->recursOn(date, KDateTime::Spec::LocalZone())) {
        occursOnDate = true;
    }
    else {
        occursOnDate = false;
    }
    return occursOnDate;
}

void CalendarModel::eventAdded(const KCalCore::Event::Ptr &event)
{
    if(eventOccursOnDate(event, viewDate)) {
        QModelIndex parent;
        beginInsertRows(parent, eventUid.size(), eventUid.size());
        QModelIndex modelIndex=index(eventUid.size(), 0);
        eventUid.append(event->uid());
        endInsertRows();
        storage->save();
        emit dataChanged(modelIndex, modelIndex);
    }
}

bool CalendarModel::removeEvent(int row)
{
    QModelIndex parent;
    // Make sure model has specified row.
    if (hasIndex(row, 0, parent)) {
        beginRemoveRows(parent, row, row);
        QString uid = eventUid.takeAt(row);
        // View can be updated now.
        endRemoveRows();
        if(!uid.isNull()) {
            // Delete the actual event
            storage->load(uid);
            KCalCore::Event::Ptr event = myCalendar->event(uid);
            if(event != NULL) {
                myCalendar->deleteEvent(event);
            }
            storage->save();
        }
        return true;
    }
    return false;
}

const QDate CalendarModel::date() const
{
    return viewDate;
}

int CalendarModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;

    return eventUid.size();
}

QVariant CalendarModel::data(const QModelIndex &index, int role) const
{
    if (index.isValid()) {
        storage->load(eventUid.at(index.row()));
        KCalCore::Event::Ptr event = myCalendar->event(eventUid.at(index.row()));
        switch (role) {
        case EventStartTimeRole:
            return QVariant(event->dtStart().time().toString("hh:mm"));
        case EventEndTimeRole:
            return QVariant(event->dtEnd().time().toString("hh:mm"));
        case EventSummaryRole:
            return QVariant(event->summary());
        case EventDescriptionRole:
            return QVariant(event->description());
        case EventLocationRole:
            return QVariant(event->location());
        case EventRecurringRole:
            return QVariant(event->recurrence()->recurs());
        }
    }
    return QVariant();
}
